#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
开发一个简单错误记录功能小模块，能够记录出错的代码所在的文件名称和行号。
处理:
1.记录最多8条错误记录，对相同的错误记录(即文件名称和行号完全匹配)只记录一条，错误计数增加；
    (文件所在的目录不同，文件名和行号相同也要合并)
2.超过16个字符的文件名称，只记录文件的最后有效16个字符；
    (如果文件名不同，而只是文件名的后16个字符和行号相同，也不要合并)
3.输入的文件可能带路径，记录文件名称不能带路径

输入:
E:\V1R2\product\fpgadrive1.c 1325
输出:
fpgadrive1.c 1235 1

file: error:log
E:\V1R2\product\fpgadrive1.c 1325
E:\V1R2\product\fpgadrive2.c 1325
E:\V1R2\product\fpgadrive3.c 1325
E:\V1R2\product\fpgadrive4.c 1325
E:\V1R2\product\fpgadrive5.c 1325
E:\V1R2\product\fpgadrive6.c 1325
E:\V1R2\product\fpgadrive7.c 1325
E:\V1R2\product\fpgadrive8.c 1325
E:\V1R2\product\fpgadoubledrive3.c 1325
E:\V1R2\product\fpgadrive8.c 1325
E:\V1R2\product\fpgadoubledrive3.c 1325
E:\V1R2\product\fpgadrive5.c 1325
E:\V1R2\product\fpgadrive10.c 1325
E:\V1R2\product\fpgadrive3.c 1325
"""

import collections
from pathlib import Path


class Record:
    RECORD_LEN = 8
    FNAME_LEN = 16

    # def __init__(self, error_log: str = 'error.log'):
    def __init__(self, error_log: str = ''):
        self.error_log = error_log
        self.error_dict = collections.OrderedDict()
        self.items = []
        if error_log:
            self.file_parse()

    def file_parse(self, file_name: str = '', clean: bool = True):
        self._clean(clean)
        with open(file_name) as log:
            for item in log:
                self.add_item(item.strip())
        self.parse()

    def add_item(self, item: str):
        if isinstance(item, str):
            self.items.append(item)
        else:
            raise TypeError('Type does not match: item should be string.')

    def parse(self, clean=False):
        self._clean(clean)
        need_move = False
        for _item in self.items:
            item = _item.split()
            fname, lineno = Path(item[0]).name[-Record.FNAME_LEN:], item[1]
            key = (fname, lineno)
            if len(self.error_dict) >= Record.RECORD_LEN:
                if key not in self.error_dict.keys():
                    head = tuple(self.error_dict.keys())[0]
                    self.error_dict.pop(head)
                else:
                    need_move = True
            self.error_dict[key] = self.error_dict.get(key, 0) + 1
            if need_move:
                self.error_dict.move_to_end(key)

    def _clean(self, yes: bool):
        if yes:
            self.items.clear()

    def __repr__(self):
        error_records = ''
        fmt = '{} {} {}\n'

        for k, v in self.error_dict.items():
            error_records += fmt.format(*k, v)
        return error_records.strip()

    __str__ = __repr__


if __name__ == '__main__':
    r = Record()
    r.add_item('E:\V1R2\product\fpgadrive20.c 1325')
    r.add_item('E:\V1R2\product\fpgadrive20.c 1325')
    r.add_item('E:\V1R2\product\fpgadrive0.c 1325')
    r.file_parse('error.log', clean=False)
    print(r)
